import json, hashlib, hmac, random, string, time
from typing import Union


class Fulianghui_Sign:

    def __init__(self, app_id: str, secret_key: str):
        self.app_id = app_id
        self.secret_key = secret_key

    @staticmethod
    def __nonce_str():
        return "".join(random.sample(string.ascii_letters + string.digits, 35)).upper()

    @staticmethod
    def __timestamp():
        return str(int(time.time()))

    @staticmethod
    def __generate_batch_str(data: Union[list, dict]):
        sort_str = ""
        if isinstance(data, list):
            sorted_data_list = [json.dumps(data, sort_keys=True) for data in data]
            sort_str = ''.join(sorted_data_list)
        if isinstance(data, dict):
            sort_str = json.dumps(data, sort_keys=True)
        return sort_str.replace(" ", "")

    def __sing(self, data: Union[list, dict], timestamp: str, nonce_str: str) -> str:
        data_str = f"timestamp={timestamp}\nnonce_str={nonce_str}\ndata={self.__generate_batch_str(data)}"
        secret_key_bytes = bytes(self.secret_key, 'utf-8')
        data_bytes = bytes(data_str, 'utf-8')
        return hmac.new(secret_key_bytes, msg=data_bytes, digestmod=hashlib.sha256).hexdigest()

    def request_data(self, data: Union[list, dict]) -> dict:
        timestamp = self.__timestamp()
        nonce_str = self.__nonce_str()
        sign = self.__sing(data, timestamp, nonce_str)
        return {
            "app_id": self.app_id,
            "timestamp": timestamp,
            "nonce_str": nonce_str,
            "data": data,
            "sign": sign
        }

    def check(self, request_data: dict) -> bool:
        data, timestamp, nonce_str, sign = map(request_data.get, ("data", "timestamp", "nonce_str", "sign"))
        my_sign = self.__sing(data, timestamp, nonce_str)
        if my_sign != sign:
            return False
        return True